#ifndef NATRIUM_UTIL_PROFILER_H
#define NATRIUM_UTIL_PROFILER_H

#include "stdafx.h"
#include "core/logger.h"

#define __PROFILE natrium::util::Profiler<natrium::core::Logger> __profiler(gLog, __FILE__, __LINE__); //the only way I know how to conveniently make use of __FILE__ and __LINE__

namespace natrium {
	namespace util {
		
		//T must implement the operator <<, typically a std::ostream or a natrium::util::logger
		template <typename T>
		class Profiler:
			public boost::noncopyable
		{
		public:
			Profiler(T& output, std::string source); //allow for slightly custom messages
			Profiler(T& output, std::string source, int line); 
			~Profiler();

		private:
			std::chrono::high_resolution_clock::time_point mStartTime;
			
			std::string mSource;
			int mLine;

			T& mOutput;
		};

		/****** Implementation ******/
		template <typename T>
		Profiler<T>::Profiler(T& output, std::string source):
			Profiler(T, source, -1) //forward to the other constructor
		{
		}

		template <typename T>
		Profiler<T>::Profiler(T& output, std::string source, int line):
			mOutput(output),
			mSource(source),
			mLine(line)
		{
			mStartTime = std::chrono::high_resolution_clock::now();
		}

		template <typename T>
		Profiler<T>::~Profiler() {
			auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - mStartTime).count();
			
			if (mLine != -1)
				mOutput << "Profile: " << mSource << " line " << mLine << " took " << duration << "ms";
			else
				mOutput << "Profile: " << mSource << " took " << duration << "ms";
		}
	}
}

#endif
